#-*- coding:Utf-8 -*-

""" imagerie ---> Ce module contient des fonctions graphiques suivant : Courbe_Temps_puits, Courbe_Voisin_Intrusion, Courbe_Voisin_Vie, Courbe, Trace_Topologie_1, Trace_Topologie_2, Trace_Topologie_Decision_1, Trace_Topologie_Decision_2, Film_Topologie, Trace_Fonction, Trace_Valeurs_Puits_1, Trace_Valeurs_Puits_2   """

from PIL import Image as im
from PIL import ImageDraw
from os import system
from math import sqrt
from copy import deepcopy
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from donnees import *
import pylab as pl


def Courbe_Temps_Puits(x, valeur) :

    """ courbe_Temps_puits(x, valeur) ---> Cette méthode permet de tracer une  courbe de variation entre le temps arrive de puits par rapport au nombre d'intrusion capter  """

    pl.clf()
    pl.plot(x, valeur, 'b-o')
    pl.xlim([0.0, max(x)])
    pl.ylim([0.0, 2000])
    pl.xlabel('Time listening of sink  ')
    pl.ylabel('Number of intrusion capture ')
    pl.title('Receiver operating characteristic ')
    pl.legend(loc = "upper right")
    pl.show()


def Courbe_Voisin_Intrusion(x, valeur) :

    """ Courbe_Voisin_Intrusion(x, valeur) ---> Cette méthode permet de tracer une courbe de variation de nombre de message qui doit diffuse au voisin par rapport au nombre d'intrusion capter """

    pl.clf()
    pl.plot(x, valeur, 'b-o')
    pl.xlim([0.0, max(x)])
    pl.ylim([0.0, 30000])
    pl.xlabel('Number of diffusion sensor  ')
    pl.ylabel('Number of intrusion capture ')
    pl.title('Receiver operating characteristic ')
    pl.legend(loc = "upper right")
    pl.show()

def Courbe_Voisin_Vie(x, valeur):

    """ Courbe_Voisin_Vie(x, valeur) ---> Cette méthode permet de tracer une courbe de variation de nombre de message qui doit diffuse au voisin par rapport au durée de vie """

    pl.clf()
    pl.plot(x, valeur, 'b-o')
    pl.xlim([0.0, max(x)])
    pl.ylim([0.5, 2])
    pl.xlabel('Number of diffusion sensor  ')
    pl.ylabel('Lifetime of the networks ')
    pl.title('Receiver operating characteristic ')
    pl.legend(loc = "upper right")
    pl.show()

def Courbe(Decision_Reel, Decision_Foret):

    """ Courbe(Decision_Reel, Decision_Foret) ---> Cette méthode permet de tracer deux courbe entre la décision des forêts aléatoires et la décision réelle  """

    X = []
    for i in range(TEMPS_SIMULATION*NOMBRE_SIMULATION):
        X.append(i)

    pl.clf()
    pl.plot(X,Decision_Reel,label='Actual decision')
    pl.plot(X,Decision_Foret,label='Decision by random forest ')
    pl.xlim([0.0, TEMPS_SIMULATION*NOMBRE_SIMULATION])
    pl.ylim([0.0, 5])
    pl.xlabel('Number of decision  ')
    pl.ylabel('The decision ')
    pl.title('Receiver operating characteristic')
    pl.legend(loc="upper right")
    pl.show()


 
def Trace_Topologie_1(Puits, nom):

    """ Trace_Topologie_1(Puits, nom ) ---> permet de tracer la topologie de réseaux si la variable Topologie est égale à 1 """

    image = im.new('RGB', (1000, 1000), color = (255, 255, 255))
    draw = ImageDraw.Draw(image)
    for ag in range(len(Puits.agregateurs)):
        if not Puits.agregateurs[ag].mort:
            for j in Puits.agregateurs[ag].capteurs:
                if not j.mort:
                    draw.line((1000*j.x, 1000*j.y, 1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y), fill=(0, 0, 0), width = 1)
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3), fill = (0, 0, 255))
                else:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3),fill = (0, 0, 0))                    
            if DIRECT_AGREGATEUR_PUITS:  
                draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.x, 1000*Puits.y), fill = (0, 255, 0), width = 1)
            else:
                if Puits.agregateurs[ag].agregateurCible == Puits:
                    draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.agregateurs[ag].agregateurCible.x, 1000*Puits.agregateurs[ag].agregateurCible.y), fill=(0,255,0), width = 1)                    
                elif not Puits.agregateurs[ag].agregateurCible.mort:
                    draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.agregateurs[ag].agregateurCible.x, 1000*Puits.agregateurs[ag].agregateurCible.y), fill=(0, 255, 0), width = 1)
            draw.rectangle((1000*Puits.agregateurs[ag].x-3, 1000*Puits.agregateurs[ag].y-3, 1000*Puits.agregateurs[ag].x+3, 1000*Puits.agregateurs[ag].y+3), fill = (255, 0, 0))
        else:
            for j in Puits.agregateurs[ag].capteurs:
                if not j.mort:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3), fill = (0, 0, 255))
                else:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3), fill = (0, 0, 0))                    
            draw.rectangle((1000*Puits.agregateurs[ag].x-3, 1000*Puits.agregateurs[ag].y-3, 1000*Puits.agregateurs[ag].x+3, 1000*Puits.agregateurs[ag].y+3), fill = (0, 0, 0))

    draw.rectangle((1000*Puits.x-10, 1000*Puits.y-10,1000*Puits.x+10, 1000*Puits.y+10),fill = (200, 164, 64))
    image.save('data/topologies/topologie_' + nom + '.png')

def Trace_Topologie_2(Puits, nom):

    """ Trace_Topologie_2(Puits, nom) ---> permet de tracer la topologie de réseaux si la variable Topologie est égale à 2 """

    image = im.new('RGB', (1000, 1000), color = (255, 255, 255))
    draw = ImageDraw.Draw(image)
    for cap in range(len(Puits.dicoCapteurs)):
        if not Puits.dicoCapteurs[cap].mort:
            if  Puits.dicoCapteurs[cap].capteurCible == Puits:
                draw.line((1000*Puits.dicoCapteurs[cap].x, 1000*Puits.dicoCapteurs[cap].y, 1000*Puits.x, 1000*Puits.y), fill = (0, 255, 0), width = 1)
                draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3),   fill = (0, 0, 255))
            else:
                if not Puits.dicoCapteurs[cap].capteurCible.mort:  
                    draw.line((1000*Puits.dicoCapteurs[cap].x, 1000*Puits.dicoCapteurs[cap].y, 1000*Puits.dicoCapteurs[cap].capteurCible.x, 1000*Puits.dicoCapteurs[cap].capteurCible.y), fill = (0,255,0), width = 1)
                    draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 255))  
                else:
                    draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 255))
        else:
            draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 0))                   
                     
            
    draw.rectangle((1000*Puits.x-10,1000*Puits.y-10,1000*Puits.x+10,1000*Puits.y+10),fill = (200,164,64))
    image.save('data/topologies/topologie_' + nom + '.png')


def Trace_Topologie_Decision_1(Puits, nom, dec):

    """ Trace_Topologie_Decision_1(Puits, dec) ---> permet de tracer la décision prise sur les données reçues par le puits si la variable Topologie est égale à 1"""

    decision = None
    if dec[0] == 0:
        decision = "Pas panne!! " 
    elif dec[0] == 1:
        decision = "Pas panne!! "
    elif dec[0] == 2:
        decision = "Pas panne!! "
    elif dec[0] == 3:
        decision = "Panne!! "
    elif dec[0] == 4:
        decision = "Panne!! "   
   
    
    image = im.new('RGB', (1000, 1000), color = (255, 255, 255))
    draw = ImageDraw.Draw(image)
    for ag in range(len(Puits.agregateurs)):
        if not Puits.agregateurs[ag].mort:
            for j in Puits.agregateurs[ag].capteurs:
                if not j.mort:
                    draw.line((1000*j.x, 1000*j.y, 1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y), fill = (0, 0, 0), width = 1)
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3),fill = (0,0,255))
                else:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3), fill = (0, 0, 0))                    
            if DIRECT_AGREGATEUR_PUITS:
                draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.x, 1000*Puits.y), fill = (0, 255, 0), width = 1)
            else:
                if Puits.agregateurs[ag].agregateurCible == Puits:
                    draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.agregateurs[ag].agregateurCible.x, 1000*Puits.agregateurs[ag].agregateurCible.y), fill=(0, 255, 0), width = 1)                    
                elif not Puits.agregateurs[ag].agregateurCible.mort:
                    draw.line((1000*Puits.agregateurs[ag].x, 1000*Puits.agregateurs[ag].y, 1000*Puits.agregateurs[ag].agregateurCible.x, 1000*Puits.agregateurs[ag].agregateurCible.y), fill=(0, 255, 0), width = 1)
            draw.rectangle((1000*Puits.agregateurs[ag].x-3, 1000*Puits.agregateurs[ag].y-3, 1000*Puits.agregateurs[ag].x+3, 1000*Puits.agregateurs[ag].y+3), fill = (255, 0, 0))
        else:
            for j in Puits.agregateurs[ag].capteurs:
                if not j.mort:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3),fill = (0, 0, 255))
                else:
                    draw.ellipse((1000*j.x-3, 1000*j.y-3, 1000*j.x+3, 1000*j.y+3),fill = (0, 0, 0))                    
            draw.rectangle((1000*Puits.agregateurs[ag].x-3, 1000*Puits.agregateurs[ag].y-3, 1000*Puits.agregateurs[ag].x+3, 1000*Puits.agregateurs[ag].y+3), fill = (0, 0, 0))

    draw.rectangle((1000*Puits.x-10, 1000*Puits.y-10, 1000*Puits.x+10, 1000*Puits.y+10), fill = (200, 164, 64))
    for i in range(10):
        draw.text((1000*Puits.x+18+(i*100),1000*Puits.y), decision, fill = (200, 160, 65))
    image.save('data/Décision/Decision_' + nom + '.png')

def Trace_Topologie_Decision_2(Puits, nom, dec):

    """ Trace_Topologie_Decision_2(Puits,dec) ---> permet de tracer la décision prise sur les données reçues par le puits si la variable Topologie est égale à 2 """
    
    decision = None

    if dec[0] == 0:
        decision = "Pas panne!! " 
    elif dec[0] == 1:
        decision = "Pas panne!! "
    elif dec[0] == 2:
        decision = "Pas panne!! "  
    elif dec[0] == 3:
        decision = "Panne!! "
    elif dec[0] == 4:
        decision = "Panne!! "  
 
 
   
    image = im.new('RGB',(1000, 1000), color = (255, 255, 255))
    draw = ImageDraw.Draw(image)
    for cap in range(len(Puits.dicoCapteurs)):
        if not Puits.dicoCapteurs[cap].mort:
            if  Puits.dicoCapteurs[cap].capteurCible == Puits:
                draw.line((1000*Puits.dicoCapteurs[cap].x, 1000*Puits.dicoCapteurs[cap].y, 1000*Puits.x, 1000*Puits.y), fill = (0, 255, 0), width = 1)
                draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 255))
            else:
                if not Puits.dicoCapteurs[cap].capteurCible.mort:  
                    draw.line((1000*Puits.dicoCapteurs[cap].x, 1000*Puits.dicoCapteurs[cap].y, 1000*Puits.dicoCapteurs[cap].capteurCible.x, 1000*Puits.dicoCapteurs[cap].capteurCible.y), fill = (0, 255, 0), width = 1)
                    draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 255))  
                else:
                    draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 255))
        else:
            draw.ellipse((1000*Puits.dicoCapteurs[cap].x-3, 1000*Puits.dicoCapteurs[cap].y-3, 1000*Puits.dicoCapteurs[cap].x+3, 1000*Puits.dicoCapteurs[cap].y+3), fill = (0, 0, 0))                   
                     
            
    draw.rectangle((1000*Puits.x-10, 1000*Puits.y-10, 1000*Puits.x+10, 1000*Puits.y+10), fill = (200, 164, 64))

    for i in range(10):
        draw.text((1000*Puits.x+18+(i*100),1000*Puits.y), decision, fill = (200, 160, 65))

    image.save('data/Décision/Decision_' + nom + '.png')




def Film_Topologie(repertoire = 'data/topologies/'):

    """ Film_Topologie(répertoire) ---> permet de créer une vidéo composée de toutes les images créées par la méthode trace_topologie_1() (si Topologie = 1) ou trace_topologie_2 (si Topologie = 2) qui sont dans le répertoire dans filmTopologie.avi """

    system("mencoder mf://" + repertoire + "*png -mf w=800:h=600:fps=5:type=png -ovc copy -oac copy -o filmTopologie.avi")    
    

def Trace_Fonction(f, repertoire = 'tmp/'):

    """ Trace_Fonction(f, répertoire) ---> On trace ce qui se passe réellement, dans videoRealite.avi """

    system('rm '+repertoire+'/*')
    F = []
    for t in range(0, 100):
        F.append(np.array([f(x/100., y/100., t/10.)/100. for x in range(100) for y in range(100)]).reshape((100, 100)))
    
    for t in range(0, 100):
        s = surf(range(100), range(100), F[t])
        savefig(repertoire + 'image_' + str(t).zfill(10) + '.png', figure = s)
        clf()
        
    system("mencoder mf://" + repertoire + "*png -mf w=800:h=600:fps=5:type=png -ovc copy -oac copy -o videoRealite.avi")    


def Trace_Valeurs_Puits_1(puits = None, repertoire = 'tmp/'):

    """ Trace_Valeurs_Puits_1(puits, répertoire) ---> permet de représenter les données reçues par le puits en fonction de la position des agrégateurs si Topologie est égale à 1, et créer une vidéo composée de toutes les images créées par cette méthode dans videoPuits.avi  """

    system('rm '+repertoire+'*')
    temps = sorted(list(set([puits.valeurs[k][0][2] for k in range(len(puits.valeurs))])))
    F = [np.array([0 for x in range(100) for y in range(100)]).reshape((100, 100))]
    
    cellules = np.array([0 for x in range(100) for y in range(100)]).reshape((100, 100))
    for x in range(100):
        for y in range(100):
            dist = sqrt((puits.agregateurs[0].x-x/100.)**2 + (puits.agregateurs[0].y-y/100.)**2)
            cellules[x][y] = 0
            for ag in range(len(puits.agregateurs)):
                if sqrt((puits.agregateurs[ag].x-x/100.)**2 + (puits.agregateurs[ag].y-y/100.)**2) < dist:
                    dist = sqrt((puits.agregateurs[ag].x-x/100.)**2 + (puits.agregateurs[ag].y-y/100.)**2)
                    cellules[x][y] = ag
    
    for t in temps:
        f = deepcopy(F[-1])
        for element in [puits.valeurs[k] for k in range(len(puits.valeurs)) if puits.valeurs[k][0][2] == t]:            
            x, y = int(100*element[0][0]), int(100*element[0][1])
            ag = cellules[x][y]
            for X in range(100):
                for Y in range(100):
                    if cellules[X][Y] == ag:
                        f[X][Y] = float(element[1])
        F.append(f)
    
    minimum = min([F[t][x][y] for t in range(len(F)) for x in range(100) for y in range(100)])
    maximum = max([F[t][x][y] for t in range(len(F)) for x in range(100) for y in range(100)])


    for tt in range(len(temps)):
        fig = plt.figure()
        ax = fig.add_subplot(111, projection = '3d')    
    
        X = np.array([[x for x in range(100)] for y in range(100)])
        Y = np.array([[y for x in range(100)] for y in range(100)])            

        ax.set_zlim3d([minimum, maximum])
        ax.plot_wireframe(X, Y, F[tt], rstride = 10, cstride = 10)
        plt.savefig(repertoire + 'image' + str(tt) + '.png')

    system("mencoder mf://" + repertoire + "*png -mf w=800:h=600:fps=5:type=png -ovc copy -oac copy -o videoPuits.avi")    



def Trace_Valeurs_Puits_2(puits = None, repertoire = 'tmp/'):

    """ Trace_Valeurs_Puits_2(puits, répertoire) --->  permet de représenter les données reçues par le puits en fonction de la position des capteurs si Topologie est égale à 2, et créer une vidéo composée de toutes les images créées par cette méthode dans videoPuits.avi  """

    system('rm ' + repertoire + '*')
    temps = sorted(list(set([puits.valeurs[k][0][2] for k in range(len(puits.valeurs))])))
    F = [np.array([0 for x in range(100) for y in range(100)]).reshape((100,100))]
    
    cellules = np.array([0 for x in range(100) for y in range(100)]).reshape((100, 100))
    for x in range(100):
        for y in range(100):
            dist = sqrt((puits.dicoCapteurs[0].x-x/100.)**2 + (puits.dicoCapteurs[0].y-y/100.)**2)
            cellules[x][y] = 0
            for ag in range(len(puits.dicoCapteurs)):
                if sqrt((puits.dicoCapteurs[ag].x-x/100.)**2 + (puits.dicoCapteurs[ag].y-y/100.)**2) < dist:
                    dist = sqrt((puits.dicoCapteurs[ag].x-x/100.)**2 + (puits.dicoCapteurs[ag].y-y/100.)**2)
                    cellules[x][y] = ag
    
    for t in temps:
        f = deepcopy(F[-1])
        for element in [puits.valeurs[k] for k in range(len(puits.valeurs)) if puits.valeurs[k][0][2] == t]:            
            x, y = int(100*element[0][0]), int(100*element[0][1])
            ag = cellules[x][y]
            for X in range(100):
                for Y in range(100):
                    if cellules[X][Y] == ag:
                        f[X][Y] = float(element[1])
        F.append(f)
    
    minimum = min([F[t][x][y] for t in range(len(F)) for x in range(100) for y in range(100)])
    maximum = max([F[t][x][y] for t in range(len(F)) for x in range(100) for y in range(100)])


    for tt in range(len(temps)):
        fig = plt.figure()
        ax = fig.add_subplot(111, projection = '3d')    
    
        X = np.array([[x for x in range(100)] for y in range(100)])
        Y = np.array([[y for x in range(100)] for y in range(100)])            

        ax.set_zlim3d([minimum, maximum])
        ax.plot_wireframe(X, Y, F[tt], rstride = 10, cstride = 10)
        plt.savefig(repertoire + 'image' + str(tt) + '.png')

    system("mencoder mf://" + repertoire + "*png -mf w=800:h=600:fps=5:type=png -ovc copy -oac copy -o videoPuits.avi")   
   

